package com.zxd.interview.chat;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

/**
 * 服务器端（ChatServer.java）
 **/
public class ChatServer {

    private static final int PORT = 12345;
    private static Map<String, PrintWriter> clientWriters = new HashMap<>();
    private static Map<String, User> onlineUsers = new HashMap<>();
    private static Map<String, Group> groups = new HashMap<>();

    public static void main(String[] args) throws IOException {
        System.out.println("Chat server started...");
        ServerSocket serverSocket = new ServerSocket(PORT);

        while (true) {
            new ClientHandler(serverSocket.accept()).start();
        }
    }

    private static class ClientHandler extends Thread {
        private Socket socket;
        private String username;
        private BufferedReader in;
        private PrintWriter out;

        public ClientHandler(Socket socket) {
            this.socket = socket;
        }

        public void run() {
            try {
                in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                out = new PrintWriter(socket.getOutputStream(), true);

                // Handle user authentication
                while (true) {
                    out.println("SUBMITNAME");
                    username = in.readLine();
                    out.println("SUBMITPASSWORD");
                    String password = in.readLine();

                    User user = User.authenticate(username, password);
                    if (user != null && !onlineUsers.containsKey(username)) {
                        synchronized (onlineUsers) {
                            onlineUsers.put(username, user);
                            clientWriters.put(username, out);
                            user.setOnline(true);
                        }
                        out.println("NAMEACCEPTED " + username);
                        break;
                    } else {
                        out.println("INVALIDCREDENTIALS");
                    }
                }

                // Notify all users about the new user
                broadcast("SERVER", username + " has joined the chat.");

                // Handle client messages
                while (true) {
                    String input = in.readLine();
                    if (input == null) {
                        return;
                    }

                    if (input.startsWith("/group")) {
                        handleGroupCommand(input);
                    } else {
                        // Log chat message
                        ChatHistory.logMessage(username + ": " + input);
                        broadcast(username, input);
                    }
                }
            } catch (IOException e) {
                System.out.println(e);
            } finally {
                // Handle user disconnect
                if (username != null) {
                    onlineUsers.remove(username);
                    clientWriters.remove(username);
                    broadcast("SERVER", username + " has left the chat.");
                }
                try {
                    socket.close();
                } catch (IOException e) {
                    System.out.println(e);
                }
            }
        }

        private void broadcast(String sender, String message) {
            for (PrintWriter writer : clientWriters.values()) {
                writer.println("MESSAGE " + sender + ": " + message);
            }
        }

        private void handleGroupCommand(String input) {
            String[] parts = input.split(" ", 3);
            if (parts.length < 3) {
                out.println("SERVER: Invalid group command.");
                return;
            }

            String command = parts[1];
            String groupName = parts[2];

            switch (command) {
                case "create":
                    if (groups.containsKey(groupName)) {
                        out.println("SERVER: Group already exists.");
                    } else {
                        Group group = new Group(groupName);
                        group.addMember(onlineUsers.get(username));
                        groups.put(groupName, group);
                        out.println("SERVER: Group " + groupName + " created.");
                    }
                    break;
                case "join":
                    Group groupToJoin = groups.get(groupName);
                    if (groupToJoin == null) {
                        out.println("SERVER: Group does not exist.");
                    } else {
                        groupToJoin.addMember(onlineUsers.get(username));
                        out.println("SERVER: Joined group " + groupName);
                    }
                    break;
                case "msg":
                    String msg = parts.length > 2 ? parts[2] : "";
                    Group groupToMsg = groups.get(groupName);
                    if (groupToMsg == null) {
                        out.println("SERVER: Group does not exist.");
                    } else {
                        for (User user : groupToMsg.getMembers()) {
                            PrintWriter writer = clientWriters.get(user.getUsername());
                            if (writer != null) {
                                writer.println("GROUP " + groupName + " " + username + ": " + msg);
                            }
                        }
                    }
                    break;
                case "members":
                    Group groupToView = groups.get(groupName);
                    if (groupToView == null) {
                        out.println("SERVER: Group does not exist.");
                    } else {
                        StringBuilder membersList = new StringBuilder("Members of " + groupName + ": ");
                        for (User user : groupToView.getMembers()) {
                            membersList.append(user.getUsername()).append(", ");
                        }
                        out.println("SERVER: " + membersList.toString());
                    }
                    break;
                default:
                    out.println("SERVER: Unknown group command.");
                    break;
            }
        }
    }

}
